package com.javabi.common.concurrent.lock;

import java.util.concurrent.locks.Lock;

import com.google.common.collect.Interner;
import com.google.common.collect.Interners;

public class InternerLockFactory<K> implements ILockFactory<K> {

	private final Interner<K> interner;
	private final ILockFactory<K> delegate;

	public InternerLockFactory(ILockFactory<K> delegate) {
		if (delegate == null) {
			throw new NullPointerException("delegate");
		}
		this.delegate = delegate;
		this.interner = Interners.newWeakInterner();
	}

	public InternerLockFactory(ILockFactory<K> delegate, Interner<K> interner) {
		if (delegate == null) {
			throw new NullPointerException("delegate");
		}
		if (interner == null) {
			throw new NullPointerException("interner");
		}
		this.delegate = delegate;
		this.interner = interner;
	}

	@Override
	public Lock getLock(K key) {
		if (key == null) {
			throw new NullPointerException("key");
		}

		// Return the interned version to guarantee the same monitor is
		// returned for two equal (but referentially different) keys
		key = interner.intern(key);

		// Delegate the lock aquisition
		return delegate.getLock(key);
	}

}
